// utils/customFetch.ts

type FetchOptions = {
  baseURL?: string; // 默认基础 URL
  timeout?: number; // 请求超时时间（毫秒）
  interceptors?: {
    request?: (config: RequestInit) => RequestInit | Promise<RequestInit>;
    response?: (response: Response) => Response | Promise<Response>;
  };
};

class CustomFetch {
  private baseURL: string;
  private timeout: number;
  private interceptors: FetchOptions["interceptors"];

  constructor(options: FetchOptions) {
    this.baseURL = options.baseURL || "";
    this.timeout = options.timeout || 5000;
    this.interceptors = options.interceptors || {};
  }

  private async fetchWithTimeout(
    url: string,
    options: RequestInit
  ): Promise<Response> {
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), this.timeout);
    const config = { ...options, signal: controller.signal };

    try {
      const response = await fetch(url, config);
      clearTimeout(timeoutId);
      return response;
    } catch (error) {
      clearTimeout(timeoutId);
      if (error instanceof DOMException && error.name === "AbortError") {
        throw new Error(`Request to ${url} timed out`);
      }
      throw error;
    }
  }

  // 请求方法
  private async request<T>(url: string, options: RequestInit = {}): Promise<T> {
    let finalOptions = options;

    // 请求拦截器
    if (this.interceptors?.request) {
      finalOptions = await this.interceptors.request(finalOptions);
    }

    const fullURL = url.startsWith("http") ? url : `${this.baseURL}${url}`;
    const response = await this.fetchWithTimeout(fullURL, finalOptions);

    // 响应拦截器
    if (this.interceptors?.response) {
      // 确保 response 拦截器总是返回 Promise<Response>
      const res = await this.interceptors.response(response);
      if (!res.ok) {
        const errorText = await res.text();
        throw new Error(
          `HTTP error! Status: ${res.status}, Message: ${errorText}`
        );
      }
      return res.json() as Promise<T>;
    }

    if (!response.ok) {
      const errorText = await response.text();
      throw new Error(
        `HTTP error! Status: ${response.status}, Message: ${errorText}`
      );
    }

    return response.json() as Promise<T>;
  }

  // GET 请求
  get<T>(url: string, options?: RequestInit): Promise<T> {
    return this.request<T>(url, { ...options, method: "GET" });
  }

  // POST 请求
  post<T>(url: string, body: unknown, options?: RequestInit): Promise<T> {
    return this.request<T>(url, {
      ...options,
      method: "POST",
      body: JSON.stringify(body),
      headers: {
        "Content-Type": "application/json",
        ...(options?.headers || {}),
      },
    });
  }

  // PUT 请求
  put<T>(url: string, body: unknown, options?: RequestInit): Promise<T> {
    return this.request<T>(url, {
      ...options,
      method: "PUT",
      body: JSON.stringify(body),
      headers: {
        "Content-Type": "application/json",
        ...(options?.headers || {}),
      },
    });
  }

  // DELETE 请求
  delete<T>(url: string, options?: RequestInit): Promise<T> {
    return this.request<T>(url, { ...options, method: "DELETE" });
  }
}

// 实例化 CustomFetch 类
const apiClient = new CustomFetch({
  baseURL: "http://localhost:3003/", // 可根据实际需求修改
  timeout: 10000, // 请求超时为 10 秒
  interceptors: {
    request: (config) => {
      // 在请求之前可以添加 token 等信息
      const token = "your-auth-token"; // 示例 token
      config.headers = {
        ...config.headers,
        Authorization: `Bearer ${token}`,
      };
      return config;
    },
    response: (response) => {
      // 处理响应，比如401未授权时的重定向
      if (response.status === 401) {
        console.error("Unauthorized! Redirecting to login...");
        // 可以在这里处理未授权的情况
      }
      return response;
    },
  },
});

export default apiClient;
